/**
 * Class: Dot2D
 *
 * Purpose: 
 *
 * Created: Jan 27, 2010 @ 9:37:10 AM
 * @author Ken Scott
 */
package org.openfantasia.ps.shape;

import org.openfantasia.ps.particle.Particle;
import org.openfantasia.ui.PFrame;
import org.openfantasia.util.math.DPoint3;
import org.openfantasia.util.math.DPointN;
import org.openfantasia.util.math.PMath;

public class HarmonicSphere extends Shape {

	public static final String BEAD_COUNT = "bead_count";

	public static final String RING_COUNT = "ring_count";

	public static final String MODULATION = "modulation";

	private boolean drawDots = true;

	private boolean drawLines = false;

	private double ringCount = 10;

	private double beadCount = 10;

	private DPointN modulation = new DPointN(6);


	public HarmonicSphere(PFrame frame) {
		super(frame);
	}


	public HarmonicSphere(PFrame frame, double weight, double ringCount, double beadCount, DPointN modulation) {
		super(frame, new DPoint3(1, 1, 1));
		setLineWeight(weight);
		setRingCount(ringCount);
		setBeadCount(beadCount);
		setModulation(modulation);
	}


	public void drawShape(Particle particle) {
		if (drawLines) {
			frame.beginShape(frame.LINES);
		}
		else if (drawDots) {
			frame.beginShape(frame.POINTS);
		}

		double numRings = getRingCount(particle);
		for (double j = 0; j < numRings; j++) {
			DPoint3 prev = null;
			double ringAngle = PMath.PI * j / numRings;

			double numBeads = getThetaSteps(particle);
			for (double k = 0; k <= numBeads; k++) {
				double beadFrac = k / numBeads;

				double beadAngle = PMath.TWO_PI * beadFrac;

				double r = 0;
				r += Math.pow(Math.sin(modulation.p[0] * ringAngle), modulation.p[1]);
				r += Math.pow(Math.cos(modulation.p[2] * ringAngle), modulation.p[3]);
				r += Math.pow(Math.sin(modulation.p[4] * beadAngle), modulation.p[5]);
				r += Math.pow(Math.cos(modulation.p[6] * beadAngle), modulation.p[7]);

				double px = r * Math.sin(ringAngle) * Math.cos(beadAngle);
				double py = r * Math.cos(ringAngle);
				double pz = r * Math.sin(ringAngle) * Math.sin(beadAngle);
				DPoint3 loc = new DPoint3(px, py, pz);

				if (drawLines && (prev != null)) {
					frame.line(loc, prev);
				}

				if (drawDots) {
					frame.point(loc);
				}

				prev = loc;
			}
		}
		frame.endShape();
	}


	public boolean isDrawDots() {
		return drawDots;
	}


	public void setDrawDots(boolean drawDots) {
		this.drawDots = drawDots;
	}


	public boolean isDrawLines() {
		return drawLines;
	}


	public void setDrawLines(boolean drawLines) {
		this.drawLines = drawLines;
	}


	public double getRingCount() {
		return ringCount;
	}


	public double getRingCount(Particle particle) {
		return (Double) getBehaviorValue(RING_COUNT, particle, getTime(), getRingCount());
	}


	public void setRingCount(double ringCount) {
		this.ringCount = ringCount;
	}


	public double getBeadCount() {
		return beadCount;
	}


	public double getThetaSteps(Particle particle) {
		return (Double) getBehaviorValue(BEAD_COUNT, particle, getTime(), getBeadCount());
	}


	public void setBeadCount(double beadCount) {
		this.beadCount = beadCount;
	}


	public DPointN getModulation() {
		return modulation;
	}


	public DPointN getModulation(Particle particle) {
		return (DPointN) getBehaviorValue(MODULATION, particle, getTime(), getModulation());
	}


	public void setModulation(DPointN modulation) {
		this.modulation = modulation;
	}
}